﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BetterHtml
{
    static class ExtensionMethods
    {
        public static char Get(this string str, int i)
        {
            return str[i < 0 ? str.Length + i : i];
        }

        public static string Slice(this string str, int? start = null, int? end = null, int step = 1)
        {
            if (step == 0) throw new ArgumentException("Step cannot be zero.", "step");

            if (start == null)
            {
                if (step > 0) start = 0;
                else start = str.Length - 1;
            }
            else if (start < 0)
            {
                if (start < -str.Length) start = 0;
                else start += str.Length;
            }
            else if (start > str.Length) start = str.Length;

            if (end == null)
            {
                if (step > 0) end = str.Length;
                else end = -1;
            }
            else if (end < 0)
            {
                if (end < -str.Length) end = 0;
                else end += str.Length;
            }
            else if (end > str.Length) end = str.Length;

            if (start == end || start < end && step < 0 || start > end && step > 0) return "";
            if (start < end && step == 1) return str.Substring((int)start, (int)(end - start));

            int length = (int)(((end - start) / (float)step) + 0.5f);
            var sb = new StringBuilder(length);
            for (int i = (int)start, j = 0; j < length; i += step, ++j)
                sb.Append(str[i]);
            return sb.ToString();
        }

        public static IEnumerable<T> Slice<T>(this IList<T> list, int? start = null, int? end = null, int step = 1)
        {
            if (step == 0) throw new ArgumentException("Step cannot be zero.", "step");

            if (start == null)
            {
                if (step > 0) start = 0;
                else start = list.Count - 1;
            }
            else if (start < 0)
            {
                if (start < -list.Count) start = 0;
                else start += list.Count;
            }
            else if (start > list.Count) start = list.Count;

            if (end == null)
            {
                if (step > 0) end = list.Count;
                else end = -1;
            }
            else if (end < 0)
            {
                if (end < -list.Count) end = 0;
                else end += list.Count;
            }
            else if (end > list.Count) end = list.Count;

            if (start == end || start < end && step < 0 || start > end && step > 0) yield break;

            int length = (int)(((end - start) / (float)step) + 0.5f);
            for (int i = (int)start, j = 0; j < length; i += step, ++j)
                yield return list[i];
        }

        public static bool IsEmpty<T>(this ICollection<T> c)
        {
            return c.Count == 0;
        }
    }
}
